﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//New and needed
using IM.Common.Message;
using IM.Domain.AppServices;

namespace IM.Domain.TransManager
{
    public class TransManagerBase:ITransManager
    {
        protected Boolean IsInTransaction;

        public Repository.IRepositoryLocator RepositoryLocator { get; set; }

        #region ITransManager Members

        public TResult ExecuteCommand<TResult>(Func<Repository.IRepositoryLocator, TResult> command) where TResult : class, Common.Message.IResponseEnvelopDTO
        {
            try
            {
                BeginTransaction();
                var result = command.Invoke(RepositoryLocator);
                CommitTransaction();
                CheckForWarnings(result);
                return result;
            }
            catch (BusinessException bex)
            {
                if (this.IsInTransaction)
                {
                    RollbackTransaction();
                }

                var type = typeof(TResult);
                var instance = Activator.CreateInstance(type, true) as IResponseEnvelopDTO;

                if (instance != null)
                {
                    instance.Response.AddBusinessException(bex);
                }

                return instance as TResult;

            }
            catch (Exception ex)
            {
                throw;
            }
        }

        public void BeginTransaction()
        {
            IsInTransaction = true;
            return;   
        }

        public void CommitTransaction()
        {
            IsInTransaction = false;
            return;
        }

        public void RollbackTransaction()
        {
            IsInTransaction = false;
            return;
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
        }

        protected bool IsDisposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!disposing)
            {
                return;
            }

            if (!IsDisposed && IsInTransaction)
            {
                RollbackTransaction();
            }

            RepositoryLocator = null;
            IsDisposed = true;
        }

        #endregion

        #region Helper methods

        void CheckForWarnings<TResult>(TResult result)
        {
           var response = result as IResponseEnvelopDTO;
            
            if (response == null)
            {
                return;
            }

            var notifier = ServiceLocator.Instance().Notifier;

            if (notifier.HasWarnings)
            {
                response.Response.AddBusinessWarnings(notifier.RetrieveWarnings()); 
            }

        }
        #endregion

    }
}
